package com.xpec.canaan.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestCompareFile
{
	public static void main(String[] args)
	{
		if( null == args || 0 == args.length )
		{
			System.out.println("invalided path");
			System.exit(0);
		}
		// 
		String inputbaseDir = args[0];
		String outputbaseDir = args[1];
		String comparebaseDir = args[2];
		// TODO add config path argument
		String binaryConfigFilePath = args[3];
		String packageConfigFilePath = args[4];
		
		TestCompareFile mainThread = new TestCompareFile(inputbaseDir,outputbaseDir,comparebaseDir, binaryConfigFilePath,packageConfigFilePath);
		
		OutputMD5Process mainProc = new OutputMD5Process(inputbaseDir, outputbaseDir, mainThread);
		mainProc.startProcess(mainThread.m_iFielProcess);
	}
	
	/**
	 * TestCompareFile test xml file difference
	 * @param basepath source path
	 */
	public TestCompareFile(String inputbaseDir, String outputbaseDir, String comparebaseDir, String binaryConfigFilePath, String packageConfigFilePath)
	{		
		m_inputBasePath = inputbaseDir;
		m_outputBasePath = outputbaseDir;
		m_compareBasePath = comparebaseDir;
		
		m_binaryConfigFilePath = binaryConfigFilePath;
		m_packageConfigFilePath = packageConfigFilePath;
		
		testStartTime = System.currentTimeMillis();
		
		m_iFielProcess = Executors.newFixedThreadPool(8);
	}
	
	public void notifyOutputComplete()
	{
		startCompare(m_compareBasePath, "xml", "config");
	}
	
	private void startCompare(String originalPath,String subDir, String filterDirName)
	{
		String originalBasePath = originalPath + subDir;
		String newBasePath = m_outputBasePath + subDir;
		CompareUnderDirectory underD = new CompareUnderDirectory(originalBasePath, newBasePath, filterDirName, this);
		try{
			underD.startCompare(m_iFielProcess);
		}
		catch(IOException excp)
		{
			System.err.println(excp.getMessage());
		}
	}
	
	public synchronized void notifyCompareFinished(String basePath, Hashtable<String ,CompareResultRecorder> results)
	{
		if( basePath.equals("xml"))
		{
			createBinaryConfigFile(results);
			m_xmlCompareResult = results;
			startCompare(m_compareBasePath, "art", "Login");
		}
		else if( basePath.equals("art"))
		{
			m_artCompareResult = results;
			startCompare(m_compareBasePath, "world_bg", null);
		}
		else if( basePath.equals("world_bg"))
		{
			m_bgCompareResult = results;
			System.out.println(basePath + " compare finished.");
			long currentTime = System.currentTimeMillis();
			System.out.println( "Spend time is:" + (currentTime-testStartTime));
			m_iFielProcess.shutdown();
			createPackageConfigFile();
		}
	}
	
	private void createBinaryConfigFile(Hashtable<String,CompareResultRecorder> results)
	{
		File conFile = new File(m_binaryConfigFilePath);
		if( conFile.exists() )
		{
			conFile.delete();
		}
		else
		{
			checkMkDirs(conFile);
		}
		
		try
		{
			RandomAccessFile binaryConfigFile = new RandomAccessFile(conFile, "rw");
			binaryConfigFile.writeBytes("input="+m_inputBasePath+"\n");
			binaryConfigFile.writeBytes("output="+m_inputBasePath+"binary\\\n");
			
			Set<String> orset = results.keySet();
			Iterator<String> oritr = orset.iterator();
			while( oritr.hasNext() )
			{
				String key = oritr.next();
				CompareResultRecorder record = results.get(key);
				// by pass base
				if( !record.getName().equals(CompareResultRecorder.CompareFileName) )
				{
					if( !record.getIsEquals() )
					{
						// has tower?
						File testF = new File(m_inputBasePath + "xml\\" + record.getName() + "\\"  + "TowerManager.xml");
						
						binaryConfigFile.writeBytes("map="+record.getName()+","+ testF.exists() +"\r\n");
					}
				}
			}
			
			binaryConfigFile.close();
		}
		catch(FileNotFoundException fnfExce)
		{
			
		}
		catch(IOException ioExce)
		{
			
		}
	}
	
	private void createPackageConfigFile()
	{
		File conFile = new File(m_packageConfigFilePath);
		if( conFile.exists() )
		{
			conFile.delete();
		}
		else
		{
			checkMkDirs(conFile);
		}
		
		try
		{
			RandomAccessFile packageConfigFile = new RandomAccessFile(conFile, "rw");
			
			packageConfigFile.writeBytes("Login\r\n");
			// by pass special case
			// art : common
			// xml : result.txt
			
			// common
			CompareResultRecorder xmlCommonRecord = m_xmlCompareResult.get(CompareResultRecorder.CompareFileName);
			CompareResultRecorder artCommonRecord = m_artCompareResult.get("Common");
			if( !xmlCommonRecord.getIsEquals() || !artCommonRecord.getIsEquals() )
			{
				packageConfigFile.writeBytes("Common\r\n");
			}
			
			// then use world_bg to decide which map should re-package
			Set<String> orset = m_bgCompareResult.keySet();
			Iterator<String> oritr = orset.iterator();
			while( oritr.hasNext() )
			{
				String key = oritr.next();
				CompareResultRecorder bgRecord = m_bgCompareResult.get(key);
				CompareResultRecorder artRecord = m_artCompareResult.get(key);
				CompareResultRecorder xmlRecord = m_xmlCompareResult.get(key);
				if( !bgRecord.getIsEquals() || !artRecord.getIsEquals() || !xmlRecord.getIsEquals() )
				{
					packageConfigFile.writeBytes(key + "\r\n");
				}
			}
			
			packageConfigFile.close();
		}
		catch(FileNotFoundException fnfExce)
		{
			
		}
		catch(IOException ioExce)
		{
			
		}
	}
	
	private void checkMkDirs(File file)
	{
		if( file.exists() )
		{
			return;
		}
		
		String myPath = file.getParent();
		File myPathD = new File(myPath);
		if( !file.exists() )
		{
			myPathD.mkdirs();
		}
	}
	
	private String m_inputBasePath;
	private String m_outputBasePath;
	private String m_compareBasePath;
	
	private String m_binaryConfigFilePath;
	private String m_packageConfigFilePath;
	
	private long testStartTime;
	
	private ExecutorService m_iFielProcess;
	
	private Hashtable<String,CompareResultRecorder> m_xmlCompareResult;
	private Hashtable<String,CompareResultRecorder> m_artCompareResult;
	private Hashtable<String,CompareResultRecorder> m_bgCompareResult;
}
